package com.platform.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentFactory;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 * <pre>
 * 功能：处理XML文档
 * </pre>
 * 
 * @author wei.gao
 */
public class XmlUtil {
	
	/**
	 * 缺省字符集
	 */
	public static final String DEFAULT_ENCODING = "UTF-8";
	
	/**
	 * <pre>
	 * 功能：新建文档
	 * </pre>
	 * 
	 * @return
	 */
	public static Document createDocument() {
		DocumentFactory factory = new DocumentFactory();
		Document document = factory.createDocument();
		return document;
	}
	
	/**
	 * <pre>
	 * 功能：给定输入流读取XML的Document
	 * </pre>
	 * 
	 * @param inputSource
	 * @param encoding
	 * @return
	 * @throws DocumentException
	 */
	public static Document fromXML(InputStream inputSource, String encoding) throws DocumentException {
		if (ValidateUtils.isBlank(encoding)) {
			encoding = DEFAULT_ENCODING;
		}
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputSource, encoding);
		return document;
	}
	
	/**
	 * 直接从字符串得到XML的Document
	 * 
	 * @param source 把一个字符串文本转化为XML的Document对象
	 * @param encoding 编码器
	 * @return <code>Document</code>
	 * @throws DocumentException
	 */
	public static Document fromXML(String source, String encoding) throws DocumentException {
		return fromXML(new ByteArrayInputStream(source.getBytes()), encoding);
	}
	
	/**
	 * <pre>
	 * 功能：把XML的Document转化为java.io.Writer输出流 不支持给定Schema文件的校验
	 * </pre>
	 * 
	 * @param document
	 * @param outStream
	 * @param encoding
	 * @throws IOException
	 */
	public static void toXML(Document document, OutputStream outStream, String encoding) throws IOException {
		//
		OutputFormat outformat = OutputFormat.createPrettyPrint();
		if (encoding == null || encoding.trim().equals("")) {
			encoding = DEFAULT_ENCODING;
		}
		//设置编码类型
		outformat.setEncoding(encoding);
		XMLWriter xmlWriter = null;
		try {
			xmlWriter = new XMLWriter(outStream, outformat);
			xmlWriter.write(document);
			xmlWriter.flush();
		} finally {
			if (xmlWriter != null) {
				try {
					xmlWriter.close();
				} catch (java.io.IOException ex) {
				}
			}
		}
	}
	
	/**
	 * <pre>
	 * 功能：把XML文档转化为String返回
	 * </pre>
	 * 
	 * @param document
	 * @param encoding
	 * @return
	 * @throws IOException
	 */
	public static String toXML(Document document, String encoding) throws IOException {
		ByteArrayOutputStream stream = new ByteArrayOutputStream();
		toXML(document, stream, encoding);
		if (stream != null) {
			try {
				stream.close();
			} catch (java.io.IOException ex) {
			}
		}
		return stream.toString();
	}
	
	/**
	 * <pre>
	 * 功能：对象转化XML
	 * </pre>
	 * 
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public static String toXML(Object obj) throws Exception {
		JAXBContext context = JAXBContext.newInstance(obj.getClass());
		Marshaller marshaller = context.createMarshaller();
		marshaller.setProperty(Marshaller.JAXB_ENCODING, "GBK");// //编码格式
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);// 是否格式化生成的xml串
		marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);// 是否省略xm头声明信息
		StringWriter writer = new StringWriter();
		marshaller.marshal(obj, writer);
		String xml = writer.toString();
		return xml.replaceFirst(" standalone=\"yes\"", "");
	}
	
	/**
	 * <pre>
	 * 功能：XML转化为对象
	 * </pre>
	 * 
	 * @param xml
	 * @param valueType
	 * @return
	 * @throws JAXBException
	 */
	@SuppressWarnings("unchecked")
	public static <T> T fromXML(String xml, Class<T> valueType) throws JAXBException {
		JAXBContext context = JAXBContext.newInstance(valueType);
		Unmarshaller unmarshaller = context.createUnmarshaller();
		return (T) unmarshaller.unmarshal(new StringReader(xml));
	}
	
}
